<template>
  <div
    class="news-list tab-default"
    ref="parent"
    @mouseenter="isHover = true" @mouseleave="isHover = false"
  >
    <div class="tab-default__wrapper container-content">
      <TabBlue
        :componentProps="modelValue"
        :currentIdx="currentIdx"
        :keySort="keySort"
        :keyFilter="keyFilter ?? []"
        :keyYear="keyYear"
        :yearList="articleYears"
        :articleTabList="tabList ? [...tabList] : undefined"
        @updateIdx="updateIdx"
        @updateSort="keySort = typeof $event === 'string' ? $event : null"
        @updateFilter="keyFilter = $event"
        @updateYear="keyYear = String($event)"
      />
    </div>
    <div class="tab-default__content mt-5 mt-md-13">
      <template v-for="(item, idx) in tabList" :key="item.key">
        <div
          v-if="idx == currentIdx"
          data-aos="fade-in"
          data-aos-duration="1500"
        >
          <div
            class="card-list row container-content-middle"
            :class="[
              `row-cols-${colMobile}`,
              `row-cols-md-${colTablet}`,
              `row-cols-lg-${colDesktop}`,
            ]"
          >
            <div
              class="card-item col"
              v-for="card in pageList"
              :key="card.id"
            >
              <CardArticle
                :componentProps="card"
                :articleCategories="articleCategories"
                :singleColumn="vsWidth < 768"
                @handle-click="handleClick"
              />
            </div>
          </div>
          <div
            v-if="totalPage > 0"
            class="flex-center mt-15 mt-md-20"
          >
            <Pagination
              :totalPage="totalPage"
              :currentPage="currentPage"
              @changePage="currentPage = $event"
            />
          </div>
        </div>
      </template>
    </div>

    <Operate v-if="!isPreview" v-model:show="isHover" @handle-edit="showSetting = true" @handle-delete="handleDelete" @handle-copy="handleCopy" @handle-paste="handlePaste"></Operate>
  </div>

  <Setting v-if="!isPreview" v-model:show="showSetting" :data="modelValue" :articleCategoryGroups="articleCategoryGroups"></Setting>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, nextTick, onBeforeUnmount } from 'vue'
import { http } from '@/utils/http'
import TabBlue from './components/TabBlue.vue'
import CardArticle from '@/common/CardArticle/index.vue'
import Pagination from './components/Pagination.vue'
import Setting from './setting.vue'
import Operate from '@/common/Operate/index.vue'
import { randomString } from '@/utils/common'

// 定义组件名称
defineOptions({
  name: 'NewsList'
})

const props = defineProps({
  modelValue: {
    type: Object,
    default: () => {}
  },

  // 是否预览
  isPreview: {
    type: Boolean,
    default: true
  },

  articleYears: { // TODO: 渲染端传入article-years
    type: Array,
    default: [
      2025,
      2024,
      2023,
      2022,
      2021,
      2020,
      2019,
      2018,
      2017,
      2016,
      2015,
      2014,
      2013,
      2012,
      2011,
      2010,
      2009
    ]
  },

  articleCategoryGroups: { // TODO: 渲染端传入article-category-groups
    type: Object,
    default: () => {return {
      "28": {
        "id": 28,
        "name": "新闻",
        "categories": [
          {
            "id": 92,
            "key": "school-news",
            "name": "学校新闻",
            "hasArticles": true
          },
          {
            "id": 291,
            "key": "events",
            "name": "活动预告",
            "hasArticles": true
          },
          {
            "id": 93,
            "key": "wechat-news",
            "name": "微信精彩文章",
            "hasArticles": true
          },
          {
            "id": 94,
            "key": "press",
            "name": "媒体报导",
            "hasArticles": true
          },
          {
            "id": 282,
            "key": "ycyw-news",
            "name": "耀中耀华新闻",
            "hasArticles": true
          },
          {
            "id": 300,
            "key": "yuiuih",
            "name": "测试",
            "hasArticles": true
          },
          {
            "id": 294,
            "key": "ycyw-event",
            "name": "耀中耀华活动",
            "hasArticles": true
          },
          {
            "id": 296,
            "key": "edfutures",
            "name": "未来教育部",
            "hasArticles": true
          }
        ]
      },
      "65": {
        "id": 65,
        "name": "媒体",
        "categories": [
          {
            "id": 274,
            "key": "meet-series",
            "name": "“遇见”系列",
            "hasArticles": true
          },
          {
            "id": 275,
            "key": "planet-leadership-series",
            "name": "星空说",
            "hasArticles": true
          },
          {
            "id": 95,
            "key": "circulars-n-newsletters",
            "name": "校內刊物",
            "hasArticles": true
          }
        ]
      },
      "101": {
        "id": 101,
        "name": "家长分享",
        "categories": [
          {
            "id": 290,
            "key": "parent-sharing",
            "name": "家长分享",
            "hasArticles": true
          }
        ]
      }
    }
  }},

  articleCategories: { // TODO: 渲染端传入article-categories
    type: Array,
    default: () => [
      {
        "id": 92,
        "key": "school-news",
        "name": "学校新闻",
        "hasArticles": true
      },
      {
        "id": 93,
        "key": "wechat-news",
        "name": "微信精彩文章",
        "hasArticles": true
      },
      {
        "id": 94,
        "key": "press",
        "name": "媒体报导",
        "hasArticles": true
      },
      {
        "id": 95,
        "key": "circulars-n-newsletters",
        "name": "校內刊物",
        "hasArticles": true
      },
      {
        "id": 222,
        "key": "planet-leadership-series-archive",
        "name": "星空说 - Archive",
        "hasArticles": true
      },
      {
        "id": 223,
        "key": "meet-series-archive",
        "name": "“遇见”系列 - Archive",
        "hasArticles": true
      },
      {
        "id": 274,
        "key": "meet-series",
        "name": "“遇见”系列",
        "hasArticles": true
      },
      {
        "id": 275,
        "key": "planet-leadership-series",
        "name": "星空说",
        "hasArticles": true
      },
      {
        "id": 282,
        "key": "ycyw-news",
        "name": "耀中耀华新闻",
        "hasArticles": true
      },
      {
        "id": 290,
        "key": "parent-sharing",
        "name": "家长分享",
        "hasArticles": true
      },
      {
        "id": 291,
        "key": "events",
        "name": "活动预告",
        "hasArticles": true
      },
      {
        "id": 294,
        "key": "ycyw-event",
        "name": "耀中耀华活动",
        "hasArticles": true
      },
      {
        "id": 296,
        "key": "edfutures",
        "name": "未来教育部",
        "hasArticles": true
      },
      {
        "id": 300,
        "key": "yuiuih",
        "name": "测试",
        "hasArticles": true
      }
    ]
  },

  website: {
    type: String,
    default: 'ywies-tx'
  },

  locale: {
    type: String,
    default: 'sc'
  }
})

const emit = defineEmits(['update:modelValue', 'handleDelete', 'handleCopy', 'handlePaste', 'handleClick'])

const handleInit = () => {
  if (props.modelValue && props.modelValue.data) return // 有数据不用初始化
  const data = {
    id: props.modelValue?.id || randomString(),
    type: 'NewsList',
    api: props.modelValue?.api || '/component/production/articles',
    previewModeApi: props.modelValue?.previewModeApi || '/component/preview/articles',
    reviewModeApi: props.modelValue?.reviewModeApi || '/component/review/articles',
    isPreviewMode: props.modelValue?.isPreviewMode || false,
    isReviewMode: props.modelValue?.isReviewMode || false,
    sort: [
      {
        key: "most-recent",
        name: "最新",
      },
      {
        key: "past-month",
        name: "上月",
      },
      {
        key: "past-year",
        name: "去年",
      }
    ],
    displayYearList: true,
    list: [],
    'article_category_group_id': 28,
    getIsPreviewMode: false,
    getIsReviewMode: false,
  }
  emit('update:modelValue', data)
} 

const isHover = ref<boolean>(false);
const showSetting = ref<boolean>(false);

const handleDelete = () => {
  emit('handleDelete', props.modelValue.id)
}

const handleCopy = () => {
  emit('handleCopy', props.modelValue)
}

const handlePaste = (type: string) => {
  emit('handlePaste', type)
}

const handleClick = (url: string) => {
  emit('handleClick', url)
}

handleInit()

// 组合式 API

// 响应式数据
const parent = ref<HTMLElement | null>(null)
const isCategoryGroup = ref(false)
const categoryGroupId = ref<string | undefined>(undefined)
const currentIdx = ref(0)
const keySort = ref<string | null>(null)
const keyFilter = ref<string[] | null>(null)
const keyYear = ref('所有年份')
const totalPage = ref(10)
const currentPage = ref(1)
const pageSize = ref(12)
const articleData = ref<any[]>([])
const articleMeta = ref<any>({})
const queryKeyValue = ref('')
const vsWidth = ref(typeof window === 'undefined' ? 1024 : window.innerWidth)

// 工具函数
const updateViewportSize = () => {
  vsWidth.value = (typeof window === 'undefined' ? 1024 : window.innerWidth)
}

// 计算属性
const articleCategories = computed(() => {
  if (!isCategoryGroup.value) {
    return Object.freeze(props.modelValue?.list ?? [])
  }

  const categoryGroups = props.articleCategoryGroups
  if (!categoryGroups || !categoryGroupId.value || !categoryGroups.hasOwnProperty(categoryGroupId.value)) {
    return Object.freeze([])
  }

  // Filter the categories that doesn't have articles when not in preview and review mode
  let categories = categoryGroups[categoryGroupId.value].categories
  if (
    !props.modelValue?.isPreviewMode &&
    !props.modelValue?.isReviewMode
  ) {
    categories = categories.filter(function(category: any) {
      return category.hasOwnProperty('hasArticles') && category.hasArticles
    })
  }

  return Object.freeze(categories)
})

const articleCategorySlugs = computed(() => {
  let categorySlugs: string[] = []
  for (const category of articleCategories.value) {
    if (category.key === 'all') {
      continue
    }
    categorySlugs.push(category.key)
  }
  return Object.freeze(categorySlugs)
})

const tabList = computed(() => {
  if (isCategoryGroup.value) {
    let categories = [
      {
        key: 'all',
        name: '全部',
        list: [],
      }
    ]

    let transformedCategories = articleCategories.value.map(function(category: any) {
      return {
        key: category.key,
        name: category.name,
        list: [],
      }
    })

    return Object.freeze(categories.concat(transformedCategories))
  }

  return props.modelValue?.list ?? undefined
})

const colDesktop = computed(() => {
  return props.modelValue?.colDesktop ?? 4
})

const colTablet = computed(() => {
  return props.modelValue?.colTablet ?? 3
})

const colMobile = computed(() => {
  return props.modelValue?.colMobile ?? 1
})

const articleList = computed(() => {
  return tabList.value?.[currentIdx.value]?.list ?? null
})

// articleList => filterList => sortList => pageList
const filterList = computed(() => {
  if (!keyFilter.value || !keyFilter.value.length) {
    return articleList.value
  }
  return articleList.value?.filter((card: any) => {
    let hasValue = false
    keyFilter.value?.forEach((item: string) => {
      hasValue = card && card.keywords && card.keywords.includes(item) ? true : hasValue
    })
    return hasValue
  }) ?? []
})

const sortList = computed(() => {
  if (!keySort.value || keySort.value === 'most-recent') {
    return [...filterList.value].sort(
      (a: any, b: any) => new Date(b.date).getTime() - new Date(a.date).getTime()
    )
  }
  const d = new Date()
  const year = d.getFullYear()
  const month = d.getMonth()
  const day = d.getDate()
  const pastM = new Date(year, month - 1 < 0 ? 11 : month - 1, day)
  const pastY = new Date(year - 1, month, day)

  const compareDate = keySort.value === 'past-month' ? pastM : pastY
  return filterList.value.filter(
    (card: any) => new Date(card.date) > compareDate && new Date(card.date) < d
  )
})

const yearList = computed(() => {
  return (props.modelValue?.displayYearList ?? true)
    ? props.articleYears
    : []
})

const pageList = computed(() => {
  if (isCategoryGroup.value || (props.modelValue?.list && props.modelValue.list[0]?.list?.length === 0)) {
    return articleData.value
  }

  return sortList.value.slice(
    (currentPage.value - 1) * pageSize.value,
    currentPage.value * pageSize.value
  )
})

// 工具函数
const scrollTo = (element: HTMLElement | null) => {
  if (!element) return
  const headerHeight = 100
  const scrollY = typeof window === 'undefined' ? 0 : window.scrollY
  const elementPosition = element.getBoundingClientRect().top + scrollY
  const offsetPosition = elementPosition - headerHeight

  if (typeof window !== 'undefined') {
    window.scrollTo({
      top: offsetPosition,
      behavior: 'smooth'
    })
  }
}

// 监听器
watch(keySort, () => {
  getArticlesList()
  resetPage()
})

watch(keyFilter, () => {
  resetPage()
})

watch(keyYear, () => {
  getArticlesList()
  resetPage()
})

watch(currentPage, () => {
  const ele = parent.value
  scrollTo(ele)
  getArticlesList()
})

watch(currentIdx, (nVal: number) => {
  resetPage()
  if (tabList.value && tabList.value[nVal]) {
    queryKeyValue.value = tabList.value[nVal].key
    currentPage.value = 1
    getArticlesList()
  }
})

watch(articleCategorySlugs, (nVal: string[], oVal: string[]) => {
  if (oVal.length === 0 && nVal.length > 0) {
    checkQuery()
    getArticlesList()
  }
})

// 方法
const getArticlesList = async () => {
  if (isCategoryGroup.value || (props.modelValue?.list && props.modelValue.list[0]?.list?.length === 0)) {
    let articlesEndpoint = props.modelValue?.api
    if (props.modelValue?.isPreviewMode) {
      articlesEndpoint = props.modelValue?.previewModeApi
    }

    if (props.modelValue?.isReviewMode) {
      articlesEndpoint = props.modelValue?.reviewModeApi
    }

    if (articleCategorySlugs.value.length === 0) {
      return
    }

    let articlesQueryParams: any = {
      per_page: pageSize.value,
      page: currentPage.value,
      filter: keySort.value,
      year: yearList.value.includes(Number(keyYear.value)) || yearList.value.includes(String(keyYear.value)) ? Number(keyYear.value) : null,
      category: !queryKeyValue.value || queryKeyValue.value === 'all' ? articleCategorySlugs.value.join(',') : queryKeyValue.value,
    }

    const config = {
      headers: {
        'api-key': 'api-key',
        application: 'website',
        website: `${props.website}-${props.locale}`,
      },
      params: articlesQueryParams,
    }

    try {
      const response = await http.get(articlesEndpoint, config)
      articleData.value = response.data.data
      articleMeta.value = response.data.meta
      totalPage.value = articleMeta.value.last_page
    } catch (error) {
      console.error('Error fetching articles:', error)
    }
  }
}

const resetPage = () => {
  currentPage.value = 1
  pageSize.value = vsWidth.value >= 768 ? (vsWidth.value >= 1024 ? 12 : 9) : 10
  if (isCategoryGroup.value || (props.modelValue?.list && props.modelValue.list[0]?.list?.length > 0)) {
    totalPage.value = Math.ceil(sortList.value.length / pageSize.value)
  }
}

const checkQuery = () => {
  let idx = 0
  if (queryKeyValue.value && tabList.value) {
    idx = tabList.value.findIndex((v: any) => v.key == queryKeyValue.value)
  }
  currentIdx.value = idx > -1 ? idx : 0
}

const updateIdx = (idx: number) => {
  currentIdx.value = idx
  queryKeyValue.value = tabList.value[idx].key
  currentPage.value = 1
  getArticlesList()
}

// 生命周期钩子
onMounted(() => {
  // 初始化分类组
  let groupId = props.modelValue?.article_category_group_id ?? null
  if (groupId) {
    isCategoryGroup.value = true
    categoryGroupId.value = groupId
  }

  // 窗口大小监听
  if (typeof window !== 'undefined') {
    window.addEventListener('resize', updateViewportSize)
  }
  updateViewportSize()

  // 初始化页面
  resetPage()
  checkQuery()

  nextTick(() => {
    getArticlesList()
  })
})

onBeforeUnmount(() => {
  if (typeof window !== 'undefined') {
    window.removeEventListener('resize', updateViewportSize)
  }
})
</script>

<style lang="scss" scoped>
.news-list {
  position: relative;
}
.tab-default {
  &__content {
    .card-list {
      --bs-gutter-x: 24px;
      --bs-gutter-y: 60px;

      @media (max-width: 767.98px) {
        --bs-gutter-x: 0;
        --bs-gutter-y: 40px;
        padding-left: 0;
        padding-right: 0;
      }
    }
  }
}

/* Minimal utilities migrated from global.scss/main.scss for NewsList */
.row {
  --bs-gutter-x: 16px;
  --bs-gutter-y: 0;
  display: flex;
  flex-wrap: wrap;
  margin-top: calc(var(--bs-gutter-y)*-1);
  margin-right: calc(var(--bs-gutter-x)*-0.5);
  margin-left: calc(var(--bs-gutter-x)*-0.5)
}

.row>* {
  flex-shrink: 0;
  width: 100%;
  max-width: 100%;
  padding-right: calc(var(--bs-gutter-x)*0.5);
  padding-left: calc(var(--bs-gutter-x)*0.5);
  margin-top: var(--bs-gutter-y)
}

.col {
  flex: 1 0 0%
}

.row-cols-auto>* {
  flex: 0 0 auto;
  width: auto
}

.row-cols-1>* {
  flex: 0 0 auto;
  width: 100%
}

.row-cols-2>* {
  flex: 0 0 auto;
  width: 50%
}

.row-cols-3>* {
  flex: 0 0 auto;
  width: 33.3333333333%
}

.row-cols-4>* {
  flex: 0 0 auto;
  width: 25%
}

.row-cols-5>* {
  flex: 0 0 auto;
  width: 20%
}

.row-cols-6>* {
  flex: 0 0 auto;
  width: 16.6666666667%
}

@media(min-width: 768px) {
  .row-cols-md-auto>* {
      flex: 0 0 auto;
      width: auto
  }

  .row-cols-md-1>* {
      flex: 0 0 auto;
      width: 100%
  }

  .row-cols-md-2>* {
      flex: 0 0 auto;
      width: 50%
  }

  .row-cols-md-3>* {
      flex: 0 0 auto;
      width: 33.3333333333%
  }

  .row-cols-md-4>* {
      flex: 0 0 auto;
      width: 25%
  }

  .row-cols-md-5>* {
      flex: 0 0 auto;
      width: 20%
  }

  .row-cols-md-6>* {
      flex: 0 0 auto;
      width: 16.6666666667%
  }
}
@media(min-width: 1024px) { 
  .row-cols-lg-auto>* {
      flex: 0 0 auto;
      width: auto
  }

  .row-cols-lg-1>* {
      flex: 0 0 auto;
      width: 100%
  }

  .row-cols-lg-2>* {
      flex: 0 0 auto;
      width: 50%
  }

  .row-cols-lg-3>* {
      flex: 0 0 auto;
      width: 33.3333333333%
  }

  .row-cols-lg-4>* {
      flex: 0 0 auto;
      width: 25%
  }

  .row-cols-lg-5>* {
      flex: 0 0 auto;
      width: 20%
  }

  .row-cols-lg-6>* {
      flex: 0 0 auto;
      width: 16.6666666667%
  }
}

.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

.px-4 { padding-left: 16px; padding-right: 16px; }
.zIndex2 { z-index: 2; }

/* spacing helpers used by this component */
.mt-5 { margin-top: 20px; }
.mt-15 { margin-top: 60px; }
@media(min-width: 768px) {
  .mt-md-3 { margin-top: 12px; }
  .mt-md-13 { margin-top: 52px; }
  .mt-md-20 { margin-top: 80px; }
}

.tab-default__content {
  display: flex;
  justify-content: center;
}
</style>
